package mornd.test7;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter;
import org.springframework.mock.http.MockHttpInputMessage;
import org.springframework.mock.http.MockHttpOutputMessage;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor;

import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

/**
 * @author: mornd
 * @dateTime: 2023/5/8 - 17:11
 * MessageConverter 测试
 */
public class Demo {

    public static void main(String[] args) throws Exception {
        testObj2Json();
        testJson2Obj();
        testObj2xml();
        System.out.println("----------------------");
        test2();
    }

    // 对象转json
    private static void testObj2Json() throws Exception {
        MockHttpOutputMessage outputMessage = new MockHttpOutputMessage();
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        if(converter.canWrite(User.class, MediaType.APPLICATION_JSON)) {
            User user = new User("张三", 20);
            converter.write(user, MediaType.APPLICATION_JSON, outputMessage);
            System.out.println(outputMessage.getBodyAsString());
        } else {
            System.out.println("该对象不能转换");
        }
    }

    // json  转对象
    private static void testJson2Obj() throws Exception {
        MockHttpInputMessage inputMessage =
                new MockHttpInputMessage("{\"name\":\"王五\",\"age\":22}".getBytes(StandardCharsets.UTF_8));
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        if(converter.canRead(User.class, MediaType.APPLICATION_JSON)) {
            Object read = converter.read(User.class, inputMessage);
            System.out.println(read.getClass());
            System.out.println(read);
        } else {
            System.out.println("该对象不能转换");
        }
    }

    // xml
    private static void testObj2xml() throws Exception {
        MockHttpOutputMessage outputMessage = new MockHttpOutputMessage();
        MappingJackson2XmlHttpMessageConverter converter = new MappingJackson2XmlHttpMessageConverter();
        if(converter.canWrite(User.class, MediaType.APPLICATION_XML)) {
            User user = new User("张三", 20);
            converter.write(user, MediaType.APPLICATION_XML, outputMessage);
            System.out.println(outputMessage.getBodyAsString());
        } else {
            System.out.println("该对象不能转换");
        }
    }

    // 模拟响应处理器中有多个解析器
    public static void test2() throws Exception {
        // 模拟请求
        MockHttpServletRequest request = new MockHttpServletRequest();
        // 模拟响应
        MockHttpServletResponse response = new MockHttpServletResponse();
        // 封装成 ServletWebRequest
        ServletWebRequest webRequest = new ServletWebRequest(request, response);

        // 控制器方法上添加 @RequestMapping(produces = "application/json") 《优先级1》
//        request.addHeader("Accept", "application/xml"); // 优先处理成 xml 格式 《优先级3》
//        response.setContentType("application/json"); // 优先级最高 《优先级2》

        // 消息转换器 多个(默认根据添加的顺序来决定)  《优先级4》
        List<HttpMessageConverter<?>> converters = new ArrayList<>();
        converters.add(new MappingJackson2XmlHttpMessageConverter());
        converters.add(new MappingJackson2HttpMessageConverter());

        // new 一个 处理 @ResponseBody 注解的返回值处理器
        RequestResponseBodyMethodProcessor processor = new RequestResponseBodyMethodProcessor(converters);

        MethodParameter methodParameter = new MethodParameter(Demo.class.getMethod("user"), -1);
        //
        System.out.println(processor.supportsParameter(methodParameter));
        // 执行目标方法
        processor.handleReturnValue(new User("王五", 23), methodParameter, new ModelAndViewContainer(), webRequest);
        // 拿到响应结果
        System.out.println(new String(response.getContentAsByteArray(), "utf-8"));
    }

    @ResponseBody
    //@RequestMapping(produces = "application/json")
    public User user() {
        return null;
    }

    @Data
    @NoArgsConstructor
    static class User {
        private String name;
        private Integer age;

        @JsonCreator
        public User(@JsonProperty("name") String name, @JsonProperty("age") Integer age) {
            this.name = name;
            this.age = age;
        }
    }
}
